package chis.fx.stage;

import java.util.Map;
import java.util.TreeMap;



import chis.fx.handlers.MyHandler;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class CopyOfBorderPaneStage extends Stage {

	// Constant data members.
	private final String stageTitle = "BorderPane Stage";
	private final double SCENE_WIDTH = 800;
	private final double SCENE_HEIGHT = 600;
	private final double SCENE_INSET_TOP = 10;
	private final double SCENE_INSET_RIGHT = 10;
	private final double SCENE_INSET_BOTTOM = 10;
	private final double SCENE_INSET_LEFT = 10;
	private final double HUD_WIDTH_PERCENT = 1;
	private final double HUD_HEIGHT_PERCENT = .30;
	private final double GAMECANVAS_WIDTH_PERCENT = 1;
	private final double GAMECANVAS_HEIGHT_PERCENT = .70;

	// Variable data members.

	// Layout dimensions.
	private double adjustedSceneWidth;
	private double adjustedSceneHeight;
	private double HUDWidth;
	private double HUDHeight;
	private double gameCanvasWidth;
	private double gameCanvasHeight;

	// Circle values.
	private double circleWidth;
	private double circleRadius;	
	private int numOfCirclesAcross;
	private int numOfCirclesDown;
	private int totalNumOfCircles;

	// Collection of clicked circle coordinates.
	private Map<Integer,MyPoint> circleCoordinates;

	private BorderPane root;
	private Scene scene;
	private FlowPane HUDPane;
	private FlowPane gameCanvasPane;
	private Group circleGroup;

	public CopyOfBorderPaneStage(int numberOfCirclesAcross) {
		numOfCirclesAcross = numberOfCirclesAcross;
		circleCoordinates = new TreeMap<Integer,MyPoint>();
		initialiseMyStage();
	}

	private void initialiseMyStage() {
		this.setResizable(false);
		this.setTitle(stageTitle);

		root = new BorderPane();
		Insets insets = new Insets(SCENE_INSET_TOP,SCENE_INSET_RIGHT,SCENE_INSET_BOTTOM,SCENE_INSET_LEFT);
		root.setPadding(insets);

		scene = new Scene(root, SCENE_WIDTH, SCENE_HEIGHT, Color.PINK);

		layoutStage();	

		this.setScene(scene);
	}

	private void layoutStage() {
		adjustSceneDimensions();
		calculateHUDDimensions();
		calculateGameCanvasDimensions();
		makeHUD();
		makeGameCanvas();
		//testing();
	}

	private void adjustSceneDimensions() {
		adjustedSceneWidth = SCENE_WIDTH - (SCENE_INSET_LEFT + SCENE_INSET_RIGHT);
		adjustedSceneHeight = SCENE_HEIGHT - (SCENE_INSET_TOP + SCENE_INSET_BOTTOM);
	}

	private void calculateHUDDimensions() {
		HUDWidth = HUD_WIDTH_PERCENT * adjustedSceneWidth;
		HUDHeight = HUD_HEIGHT_PERCENT * adjustedSceneHeight;
	}

	private void calculateGameCanvasDimensions() {
		gameCanvasWidth = GAMECANVAS_WIDTH_PERCENT * adjustedSceneWidth;
		gameCanvasHeight = GAMECANVAS_HEIGHT_PERCENT * adjustedSceneHeight;
	}

	private void makeHUD() {
		HUDPane = new FlowPane();
		HUDPane.setPrefSize(HUDWidth, HUDHeight);
		root.setTop(HUDPane);
	}

	private void makeGameCanvas() {
		gameCanvasPane = new FlowPane();
		gameCanvasPane.setPrefSize(gameCanvasWidth, gameCanvasHeight);
		initialiseCircleCollectionDimensions();

		for (int x = 0; x < totalNumOfCircles; x ++) {
			Circle c = new Circle(circleRadius, Color.web("white", 1));
			//c.setOnMouseClicked(null);
			c.addEventHandler(MouseEvent.MOUSE_CLICKED, makeCircleClickHandler());
			c.addEventHandler(MouseEvent.MOUSE_MOVED, makeCircleMovedHandler());
			gameCanvasPane.getChildren().add(c);
		}

		root.setCenter(gameCanvasPane);
	}

	private EventHandler<MouseEvent> makeCircleClickHandler(){
		EventHandler<MouseEvent> clickHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				MyPoint p = new MyPoint(event.getSceneX(),event.getSceneY());
				addClickedCircle(p);
			}
		};
		return clickHandler;
	}

	private void addClickedCircle(MyPoint clicked) {
		// Find the top left corner coordinates of the game canvas pane.
		int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
		double minX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinX();
		double minY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinY();

		//		print("clicked.getX()", clicked.getX());
		//		print("clicked.getY()", clicked.getY());
		//		print("pane minX", minX);
		//		print("pane minY", minY);

		// Adjust the clicked coordinate in the scene
		// to the actual coordinate in the game canvas.
		double adjustedX = clicked.getX() - minX;
		double adjustedY = clicked.getY() - minY;

		//		print("adjustedX", adjustedX);
		//		print("adjustedY", adjustedY);

		// Get the position the shape occupies on screen.
		// eg. 1 across, 2 down.
		int xPos = getPosition(adjustedX);
		int yPos = getPosition(adjustedY);

		//		print("xPos", xPos);
		//		print("yPos", yPos);

		// Get the index of the shape in the collection
		int position = getPositionInGrid(xPos,yPos);

		//print("Position",position);

		// Put the position/index and coordinates 
		// of the shape in the map.
		MyPoint p = getCoordinates(xPos,yPos);
		circleCoordinates.put(position, p);
		
		print("Added Position:: ",position);
		print("Added MyPoint:: ",p.toString());
		
		print("circleCoordinates.size", circleCoordinates.size());

	}

	private MyPoint getCoordinates(int xPos, int yPos) {
		MyPoint p = new MyPoint();
		int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
		double minX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinX();
		double minY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinY();
		p.setX(minX + (xPos * circleWidth));
		p.setY(minY + (yPos * circleWidth));
		return p;
	}

	private int getPosition(double clickedCoord) {
		int pos = (int) (clickedCoord / circleWidth);
		return pos;
	}

	public int getPositionInGrid(int xPos, int yPos) {
		// xPos and yPos range begin from 0.
		// Convert xPos and yPos to position numbers
		// by adding 1.
		int convertToPositionNumberX = xPos + 1;
		int convertToPositionNumberY = yPos + 1;
		int positionNumber;
		int balanceOfRow = numOfCirclesAcross - convertToPositionNumberX;
		print("Balance of row", balanceOfRow);
		positionNumber = (numOfCirclesAcross * convertToPositionNumberY) - balanceOfRow;
		// Convert the position back to a range beginning with 0
		// to ensure it's correct position in collections.
		int indexPosition = positionNumber - 1;
		return indexPosition;
	}


	private EventHandler<MouseEvent> makeCircleMovedHandler(){
		EventHandler<MouseEvent> movedHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println(event.getSceneX());
				System.out.println(event.getSceneY());
			}
		};
		return movedHandler;
	}

	private void initialiseCircleCollectionDimensions() {
		circleWidth = gameCanvasWidth / numOfCirclesAcross;
		circleRadius = circleWidth / 2;
		numOfCirclesDown = (int) (gameCanvasHeight / circleWidth);
		totalNumOfCircles = numOfCirclesAcross * numOfCirclesDown;
	}

	//	private void addClickedCircle(MyPoint clicked) {
	//		print("clicked.getX()", clicked.getX());
	//		print("clicked.getY()", clicked.getY());
	//
	//		int xPos = getPosition(clicked.getX());
	//		int yPos = getPosition(clicked.getY());
	//
	//		print("xPos position", xPos);
	//		print("yPos position", yPos);
	//		int position = getPositionInGrid(xPos,yPos);
	//		print("getPositionInGrid", position);
	//
	//
	//		MyPoint p = getCoordinates(xPos,yPos);
	//
	//		//MyPoint topLeft = makeTopLeftPoint(clicked);
	//
	//		circleCoordinates.put(position, p);
	//
	//		print("Position", position);
	//		print("circleCoordinates.size: ", circleCoordinates.size());
	//		//print("circleCoordinates: ", circleCoordinates);
	//		//		int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
	//		//		double minX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinX();
	//		//		double minY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinY();
	//		//		
	//		//		print("Min x cvp", minX);
	//		//		print("Min y cvp", minY);
	//
	//
	//	}

	//	public int getPositionInGrid(int xPos, int yPos) {
	////		int positionInRow = (int) (topLeft.getX() / circleWidth);
	////		int rowNumber = (int) (topLeft.getY() / circleWidth);
	//		int position;
	//		int balanceOfRow = numOfCirclesAcross - xPos;
	//		position = (xPos * yPos) - balanceOfRow;
	//		
	//		//position = (yPos * numOfCirclesAcross) - balanceOfRow;
	//		return position;
	////		int positionInRow = (int) (topLeft.getX() / circleWidth);
	////		int rowNumber = (int) (topLeft.getY() / circleWidth);
	////		int position;
	////		int balanceOfRow = numOfCirclesAcross - positionInRow;
	////		position = (rowNumber * numOfCirclesAcross) - balanceOfRow;
	////		return position;
	//	}







	//	private MyPoint getPositionInGrid(MyPoint clicked) {
	//	MyPoint p = new MyPoint();
	//	int x = clicked.getX();
	////	Double dx = new Double(clicked.getX());
	////	Double dy = new Double(clicked.getY());
	////	Double cw = new Double(circleWidth);
	////	p.setX(dx / cw);
	////	p.setY(dy / cw);
	////	print("p.getX()",p.getX());
	////	print("p.getY()",p.getY());
	////	print("cw",cw);
	//	return p;
	//}

	//	private MyPoint makeTopLeftPoint(MyPoint clicked) {
	//		
	//		int xPos = getPosition(clicked.getX());
	//		int yPos = getPosition(clicked.getY());
	//		int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
	//		double minX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinX();
	//		double minY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinY();
	//		MyPoint p = new MyPoint();
	//	return null;
	//	}
	//	private MyPoint makeTopLeftPoint(MyPoint clicked) {
	//		MyPoint p = new MyPoint();
	//		Double dx = new Double(clicked.getX());
	//		Double dy = new Double(clicked.getY());
	//		Double cw = new Double(circleWidth);
	//		p.setX(dx / cw);
	//		p.setY(dy / cw);
	//		print("p.getX()",p.getX());
	//		print("p.getY()",p.getY());
	//		print("cw",cw);
	//
	//
	//		return p;
	//	}



	private void getLocationOfGameCanvasInParent() {
		int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
		double minX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinX();
		double minY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinY();
		double maxX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMaxX();
		double maxY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMaxY();
	}

	private EventHandler<MouseEvent> makeBorderPaneMovedHandler(){
		EventHandler<MouseEvent> clickHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("BorderPane " + event.getSceneX());
				System.out.println("BorderPane " + event.getSceneY());
			}
		};
		return clickHandler;
	}

	private EventHandler<MouseEvent> makeFlowPaneMovedHandler(){
		EventHandler<MouseEvent> clickHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("FlowPane " + event.getSceneX());
				System.out.println("FlowPane " + event.getSceneY());
				int iHUDPane = root.getChildren().indexOf(HUDPane);
				System.out.println("iHUDPane: " + iHUDPane);
				int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
				System.out.println("igameCanvasPane: " + igameCanvasPane);
				System.out.println("BOUNDS: " + root.getChildren().get(igameCanvasPane).getBoundsInParent());
			}
		};
		return clickHandler;
	}

	private void print(String tag, Object value) {
		System.out.println(tag + " " + value);
	}

	private void testing() {
		print("SCENE_WIDTH",SCENE_WIDTH);
		print("SCENE_HEIGHT",SCENE_HEIGHT);
		print("SCENE_INSET_TOP",SCENE_INSET_TOP);
		print("SCENE_INSET_RIGHT",SCENE_INSET_RIGHT);
		print("SCENE_INSET_BOTTOM",SCENE_INSET_BOTTOM);
		print("SCENE_INSET_LEFT",SCENE_INSET_LEFT);
		print("HUD_WIDTH_PERCENT",HUD_WIDTH_PERCENT);
		print("HUD_HEIGHT_PERCENT",HUD_HEIGHT_PERCENT);
		print("GAMECANVAS_WIDTH_PERCENT",GAMECANVAS_WIDTH_PERCENT);
		print("GAMECANVAS_HEIGHT_PERCENT",GAMECANVAS_HEIGHT_PERCENT);
		print("adjustedSceneWidth",adjustedSceneWidth);
		print("adjustedSceneHeight",adjustedSceneHeight);
		print("HUDWidth",HUDWidth);
		print("HUDHeight",HUDHeight);
		print("gameCanvasWidth",gameCanvasWidth);
		print("gameCanvasHeight",gameCanvasHeight);
		print("circleWidth",circleWidth);
		print("circleRadius",circleRadius);
		print("numOfCirclesAcross",numOfCirclesAcross);
		print("numOfCirclesDown",numOfCirclesDown);
		print("totalNumOfCircles",totalNumOfCircles);

		root.addEventHandler(MouseEvent.MOUSE_MOVED, makeBorderPaneMovedHandler());

		gameCanvasPane.addEventHandler(MouseEvent.MOUSE_MOVED, makeFlowPaneMovedHandler());


	}


}
